package vashion.azeroth.core.manager.forest;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import vashion.azeroth.contant.AzerothConstants;
import vashion.azeroth.contant.ForestErrorEnum;
import vashion.azeroth.core.common.NeedOperateFlow;
import vashion.azeroth.core.dao.BaseDao;
import vashion.azeroth.core.item.dao.ForestDao;
import vashion.azeroth.core.item.pojo.ForestDO;
import vashion.azeroth.core.item.pojo.ForestTreeAndBrandDO;
import vashion.azeroth.core.item.pojo.ForestTreeDO;
import vashion.azeroth.core.item.pojo.ItemForestBrandDO;
import vashion.azeroth.core.manager.impl.BaseManagerImpl;
import vashion.azeroth.core.manager.item.BaseItemForestBrandManager;
import vashion.azeroth.core.pojo.common.OperateFlowEnum;
import vashion.azeroth.core.result.ApiResult;

/**
 * Created by tingting on 15/9/1. 基础的类目管理,目前类目树只有两级，先临时写成hashMap，待改造
 */
@Service
public class BaseForestManager extends BaseManagerImpl<ForestDO> {

	private final static Logger log = LoggerFactory.getLogger(BaseForestManager.class);

	/**
	 * 内存里的类目树
	 */
	private Map<ForestDO, List<ForestDO>> forestMap = new HashMap<ForestDO, List<ForestDO>>();

	private AtomicBoolean isBuilding = new AtomicBoolean(false);

	@Autowired
	private ForestDao forestDao;
	@Autowired
	private BaseItemForestBrandManager baseItemForestBrandManager;

	@Override
	public BaseDao<ForestDO> getDao() {
		return forestDao;
	}

	/**
	 * 获取类目树
	 *
	 * @return
	 */
	public ApiResult<Map<ForestDO, List<ForestDO>>> getForestTree() {
		if (CollectionUtils.isEmpty(forestMap)) {
			rebuildForestMap();
		}
		return ApiResult.newSuccessResult(forestMap);
	}

	/**
	 * 获取类目树
	 *
	 * @return
	 */
	public ApiResult<List<ForestTreeDO>> getForestTreeByTitle(ForestDO forestDO) {
		if (CollectionUtils.isEmpty(forestMap)) {
			rebuildForestMap();
		}
		forestDO.getTitle();
		List<ForestTreeDO> forestTreeList = Lists.<ForestTreeDO>newArrayList();
		for (Map.Entry<ForestDO, List<ForestDO>> entry : forestMap.entrySet()) {
			ForestTreeDO forestTree = new ForestTreeDO();
			ForestDO parentDO = entry.getKey();
			if (null != parentDO) {
				List<ForestDO> children = entry.getValue();
				// 按标题查询
				if (null != forestDO.getTitle()) {
					boolean withGivenTitle = false;
					if (null != parentDO.getTitle() && parentDO.getTitle().contains(forestDO.getTitle())) {
						withGivenTitle = true;
					} else {
						for (ForestDO child : children) {
							if (null != child.getTitle() && child.getTitle().contains(forestDO.getTitle())) {
								withGivenTitle = true;
								break;
							}
						}
					}
					if (!withGivenTitle) {
						continue;
					}
				}
				forestTree.setParentDO(parentDO);
				forestTree.setChildList(children);
				forestTreeList.add(forestTree);
			}
		}
		//分页
		List<ForestTreeDO> subList = Lists.<ForestTreeDO>newArrayList();
		int firstRow = forestDO.getFirstRow();
		int lastRow = forestDO.getFirstRow() + forestDO.getPageSize();
		if (firstRow < forestTreeList.size()) {
			if (lastRow > forestTreeList.size()) {
				lastRow = forestTreeList.size();
			}
			subList = forestTreeList.subList(firstRow, lastRow);
		}
		ApiResult<List<ForestTreeDO>> result = ApiResult.newSuccessResult(subList);
		result.setTotalCount(forestTreeList.size());
		return result;
	}

	/**
	 * 重新构造类目树
	 */
	private void rebuildForestMap() {

		if (!isBuilding.compareAndSet(false, true)) {
			log.error("rebuildForestMap is running!");
			return;
		}
		try {
			ForestDO queryForestDO = new ForestDO();
			// queryForestDO.setStatus(AzerothConstants.ItemForest.NORMAL);
			queryForestDO.setPageSize(1000);
			List<ForestDO> forestDOList = this.find(queryForestDO);
			Map<Long, List<ForestDO>> tempMap = new HashMap<Long, List<ForestDO>>();
			Map<Long, ForestDO> beanMap = new HashMap<Long, ForestDO>();
			for (ForestDO forestDO : forestDOList) {
				beanMap.put(forestDO.getId(), forestDO);
				if (null == forestDO.getParentId() || 0 == forestDO.getParentId()) {
					tempMap.put(forestDO.getId(), Lists.<ForestDO>newArrayList());
				} else {
					if (!tempMap.containsKey(forestDO.getParentId())) {
						tempMap.put(forestDO.getParentId(), Lists.<ForestDO>newArrayList());
					}
					tempMap.get(forestDO.getParentId()).add(forestDO);
				}
			}
			Map<ForestDO, List<ForestDO>> resultMap = Maps.newHashMap();
			for (Map.Entry<Long, List<ForestDO>> entry : tempMap.entrySet()) {
				resultMap.put(beanMap.get(entry.getKey()), entry.getValue());
			}
			forestMap = resultMap;
		} catch (Exception e) {
			log.error("rebuildForestMap error", e);
		}
		isBuilding.compareAndSet(true, false);
	}

	private void clearForestMap() {
		if (!isBuilding.compareAndSet(false, true)) {
			log.error("rebuildForestMap is running!");
			return;
		}
		forestMap = new HashMap<ForestDO, List<ForestDO>>();
		isBuilding.compareAndSet(true, false);
	}

	public ApiResult<ForestDO> getDetail(long forestId) {

		ForestDO forestDO;
		try {
			forestDO = this.get(forestId);
		} catch (Exception e) {
			log.error("BaseForestManager.get error forestId=" + forestId, e);
			return ApiResult.newErrorResult(ForestErrorEnum.QUERY_ERROR.getErrorCode(),
					ForestErrorEnum.QUERY_ERROR.getErrorMessage());
		}
		return ApiResult.newSuccessResult(forestDO);
	}
	
	public ApiResult<ForestTreeAndBrandDO> getDetailWithBrandList(long forestId) {
		ForestDO forestDO = this.getDetail(forestId).getData();
		if (null == forestDO || 0 == forestDO.getId()) {
			return ApiResult.newErrorResult(ForestErrorEnum.IS_NULL.getErrorCode(),
					ForestErrorEnum.IS_NULL.getErrorMessage());
		}
		ForestTreeAndBrandDO forestWithBrandList = new ForestTreeAndBrandDO();
		forestWithBrandList.setParentDO(forestDO);
		//获取关联的品牌列表
		ItemForestBrandDO itemForestBrandDO = new ItemForestBrandDO();
		itemForestBrandDO.setForestId(forestId);
		itemForestBrandDO.setPageSize(10000);
		List<ItemForestBrandDO> itemForestBrandList = baseItemForestBrandManager
				.getBrandListByForestId(itemForestBrandDO).getData();
		forestWithBrandList.setForestBrandList(itemForestBrandList);
		return ApiResult.newSuccessResult(forestWithBrandList);
	}

	/**
	 * 新增类目
	 *
	 * @param forestDO
	 * @param operateId
	 * @param brandIds
	 * @return
	 */
	@NeedOperateFlow(operateIdArgLocation = 2, operateFlowEnum = OperateFlowEnum.FOREST)
	public ApiResult<Boolean> publishForest(ForestDO forestDO, String brandIds, long operateId) {

		if (null == forestDO || StringUtils.isBlank(forestDO.getTitle())) {
			return ApiResult.newErrorResult(ForestErrorEnum.ARG_ERROR.getErrorCode(),
					ForestErrorEnum.ARG_ERROR.getErrorMessage());
		}
		forestDO.setGmtCreate(new Date());
		forestDO.setGmtModified(new Date());
		forestDO.setUserId(operateId);
		// 是否已存在检查
		ForestDO dbValue = this.findByTitle(forestDO.getTitle());
		if (null != dbValue) {
			return ApiResult.newErrorResult(ForestErrorEnum.ALREADY_EXITS.getErrorCode(),
					ForestErrorEnum.ALREADY_EXITS.getErrorMessage());
		}
		try {
			forestDO = this.save(forestDO);
			// 保存类目品牌关联的表
			baseItemForestBrandManager.publishBrandIdListForest(brandIds, forestDO, operateId);
		} catch (Exception e) {
			log.error("BaseForestManager.publishForest error, forestD=" + forestDO, e);
			return ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
					ForestErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
		clearForestMap();
		return ApiResult.newSuccessResult(true);
	}

	private ForestDO findByTitle(String title) {
		return forestDao.findByTitle(title);
	}

	/**
	 * 新增类目
	 *
	 * @param forestDO
	 * @param operateId
	 * @return
	 */
	@NeedOperateFlow(operateIdArgLocation = 2, operateFlowEnum = OperateFlowEnum.FOREST)
	public ApiResult<Boolean> updateForest(ForestDO forestDO, String brandIds, long operateId) {

		if (null == forestDO || StringUtils.isBlank(forestDO.getTitle()) || 0 == forestDO.getId()) {
			return ApiResult.newErrorResult(ForestErrorEnum.ARG_ERROR.getErrorCode(),
					ForestErrorEnum.ARG_ERROR.getErrorMessage());
		}
		// 新名字是否已存在检查
		ForestDO dbValue = this.findByTitle(forestDO.getTitle());
		if (null != dbValue && forestDO.getId() != dbValue.getId()) {
			return ApiResult.newErrorResult(ForestErrorEnum.ALREADY_EXITS.getErrorCode(),
					ForestErrorEnum.ALREADY_EXITS.getErrorMessage());
		}
		try {
			this.update(forestDO);
			// 更新保存类目品牌关联的表
			baseItemForestBrandManager.updateBrandIdListForest(brandIds, forestDO, operateId);
		} catch (Exception e) {
			log.error("BaseForestManager.update error, forestDO=" + forestDO, e);
			return ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
					ForestErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
		clearForestMap();
		return ApiResult.newSuccessResult(true);
	}

	/**
	 * 冻结类目
	 * 
	 * @param forestId
	 * @param operateId
	 * @return
	 */
	@NeedOperateFlow(operateIdArgLocation = 1, operateFlowEnum = OperateFlowEnum.FOREST)
	public ApiResult<Boolean> deleteForest(long forestId, long operateId) {

		ForestDO forestDO = this.getDetail(forestId).getData();
		if (null == forestDO) {
			return ApiResult.newErrorResult(ForestErrorEnum.IS_NULL.getErrorCode(),
					ForestErrorEnum.IS_NULL.getErrorMessage());
		}
		boolean updateSuccess;
		try {
			forestDO.setStatus(AzerothConstants.ItemForest.DELETE);
			updateSuccess = this.remove(forestDO) > 0;
			// 冻结子类目
			List<ForestDO> childrenForestList = this.getChildrenForestList(forestDO.getId()).getData();
			if (!CollectionUtils.isEmpty(childrenForestList)) {
				for (ForestDO childForest : childrenForestList) {
					childForest.setStatus(AzerothConstants.ItemForest.DELETE);
					this.remove(childForest);
				}
			}
		} catch (Exception e) {
			log.error("baseForestManager.deleteForest error, operateId=" + operateId, e);
			return ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
					ForestErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
		return updateSuccess ? ApiResult.newSuccessResult(true)
				: ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
						ForestErrorEnum.SYSTEM_ERROR.getErrorMessage(), false);
	}

	/**
	 * 解冻类目
	 * 
	 * @param forestId
	 * @param operateId
	 * @return
	 */
	@NeedOperateFlow(operateIdArgLocation = 1, operateFlowEnum = OperateFlowEnum.FOREST)
	public ApiResult<Boolean> resumeForest(long forestId, long operateId) {

		ForestDO forestDO = this.getDetail(forestId).getData();
		if (null == forestDO) {
			return ApiResult.newErrorResult(ForestErrorEnum.IS_NULL.getErrorCode(),
					ForestErrorEnum.IS_NULL.getErrorMessage());
		}
		boolean updateSuccess;
		try {
			forestDO.setStatus(AzerothConstants.ItemForest.NORMAL);
			updateSuccess = this.remove(forestDO) > 0;
		} catch (Exception e) {
			log.error("baseForestManager.resumeForest error, operateId=" + operateId, e);
			return ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
					ForestErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
		return updateSuccess ? ApiResult.newSuccessResult(true)
				: ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
						ForestErrorEnum.SYSTEM_ERROR.getErrorMessage(), false);
	}

	/**
	 * 查询类目
	 *
	 * @param forestDO
	 * @return
	 */
	public ApiResult<List<ForestDO>> getForestList(ForestDO forestDO) {

		try {
			List<ForestDO> forestDOList = this.find(forestDO);
			return ApiResult.newSuccessResult(forestDOList);
		} catch (Exception e) {
			log.error("BaseForestManager.getForestList error forestDO=" + forestDO, e);
			return ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
					ForestErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
	}

	/**
	 * 查询一级或者二级类目
	 *
	 * @param forestDO
	 * @return
	 */
	public ApiResult<List<ForestDO>> getParentsOrChildrenForestList(ForestDO forestDO) {

		try {
			List<ForestDO> forestDOList = forestDao.findParentsOrChildren(forestDO);
			return ApiResult.newSuccessResult(forestDOList);
		} catch (Exception e) {
			log.error("BaseForestManager.findParentsOrChildren error forestDO=" + forestDO, e);
			return ApiResult.newErrorResult(ForestErrorEnum.SYSTEM_ERROR.getErrorCode(),
					ForestErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
	}

	public ForestDO getWithCache(long forestId) {
		if (CollectionUtils.isEmpty(forestMap)) {
			return this.get(forestId);
		}
		for (List<ForestDO> forestDOList : forestMap.values()) {
			for (ForestDO forestDO : forestDOList) {
				if (forestDO.getId() == forestId) {
					return forestDO;
				}
			}
		}
		return null;
	}

	/**
	 * 查询子类目列表
	 *
	 * @param parentId
	 * @return
	 */
	public ApiResult<List<ForestDO>> getChildrenForestList(long parentId) {
		ForestDO forestDO = new ForestDO();
		forestDO.setParentId(parentId);
		forestDO.setPageSize(1000);
		return getForestList(forestDO);
	}
}
